import RNFetchBlob from 'rn-fetch-blob'
import * as XLog from "../libs/XLog";
import * as LogicConstant from "./LogicConstant";
import * as CommunicationManager from './CommunicationManager';
import * as TopicUtil from './TopicUtil';
import * as DataCenter from './DataCenter';
import * as Utils from './Utils';
import * as SerialPortManager from './SerialPortManager';
import * as ErrorRecoveryManager from './ErrorRecoveryManager';
import * as AsyncDataManager from './AsyncDataManager';
import * as CommandManager from './CommandManager';
import * as StrategyManager from './StrategyManager';
import * as UICommandExecute from './UICommandExecute';
import * as ReactNative from 'react-native';
import UpgradeLibrary from '../libs/Upgrade';
import * as RNStorage from '../common/Storage/AppStorage';
import * as CodePush from "react-native-code-push";
// import {resolve} from Promise;

export default class DebugManager{
    static debugEventHandler = {};
    static installDebugManager(){
        this.addHandler("upload", this.upload);
        this.addHandler("mqtt_server", this.debug_mqtt_server);
        this.addHandler("mqtt_local", this.debug_mqtt_local);
        this.addHandler("mqtt_remote", this.debug_mqtt_remote);
        this.addHandler("eval", this.debug_eval);
        this.addHandler("topic", this.debug_topic);
        this.addHandler("log", this.debug_log);
        this.addHandler("upgrade", this.debug_upgrade);
        this.addHandler("command", this.debug_command);
        this.addHandler("serial", this.debug_serial);
        this.debugEventListener = ReactNative.DeviceEventEmitter.addListener("debug", (data)=>{
            DebugManager.dispatchEvent(data);
        });
    }

    static uninstallDebugManager() {
        if(this.debugEventListener) {
            this.debugEventListener.remove();
            this.debugEventListener = null;
        }
    }

    static addHandler(operation, callback){
        this.debugEventHandler[operation] = callback;
    }

    static dispatchEvent(data){
        try{
            if(data.operation && this.debugEventHandler[data.operation]){
                this.debugEventHandler[data.operation](data.param);
            }
        }catch(error) {
            DebugManager.commonAnswer2Remote("dispatch exception：" + error?.message + "|" + data);
        }
    }

    static commonAnswer2Remote(msg) {
        CommunicationManager.default.send2Remote(TopicUtil.formatterTopic(LogicConstant.Topic_Debug_Reply,
            DataCenter.default.serverId, DataCenter.default.gateId, LogicConstant.ProductID.LOOP),
            Utils.commonMakeRsp2Request(msg,
                LogicConstant.Topic_Debug_Reply.method));
    }

    // {
    //     "params":
    //     {
    //       "operation": "upload",
    //       "param": {"date": "20211207", "url": "http://192.168.2.54:8000/"}
    //     },
    //     "method": "thing.gate.debug"
    // }
    static async upload(param){
        if(param){
            let path = await XLog.default.getLogPath();
            let log_full_path = path + "/" + "monitor_" + param.date + ".xlog";
            RNFetchBlob.fs.exists(log_full_path)
            .then((exist) => {
                if(exist) {
                    RNFetchBlob.fetch('POST', param.url, {
                        'Content-Type' : 'octet-stream',
                    }, [
                        { name: "file", filename: "monitor_" + param.date + ".xlog", type: 'file', 
                        data: RNFetchBlob.wrap(log_full_path) },
                        //... 可能还会有其他非文件字段{name:'字段名',data:'对应值'}
                      ])
                    .then((res) => {
                        DebugManager.commonAnswer2Remote("upload success");
                    })
                    .catch((err) => {
                        DebugManager.commonAnswer2Remote("upload failed: " + err);
                    })
                } else {
                    DebugManager.commonAnswer2Remote(`${log_full_path} file not exist`);
                }
            })
            .catch(() => { 
                DebugManager.commonAnswer2Remote(`${log_full_path} file exist exception`);
             });
        }        
    }

    // {
    //     "params": {
    //         "operation": "mqtt_server"
    //     },
    //     "method": "thing.gate.debug"
    // }
    static async debug_mqtt_server(param) {
        try{
            await CommunicationManager.default.destroyMqttServer();
            let ret = await CommunicationManager.default.createMqttServer();
            DebugManager.commonAnswer2Remote("broker：" + ret ? "成功" :"错误");
        }catch(error) {
            DebugManager.commonAnswer2Remote("broker exception：" + error);
        }
    }

    // {
    //     "params": {
    //         "operation": "mqtt_local",
    //         "param":{"masterIp":"129.204.245.148"}
    //     },
    //     "method": "thing.gate.debug"
    // }
    static async debug_mqtt_local(param) {
        if(param) {
            try{
                await CommunicationManager.default.destroyLocalMqttClient();
                await CommunicationManager.default.createLocalMqttClient(param.masterIp, (status)=>{
                    DebugManager.commonAnswer2Remote("本地连接情况：" + status);
                });
            }catch(error) {
                DebugManager.commonAnswer2Remote("local mqtt exception：" + error);
            }
        }
    }

    // {
    //     "params": {
    //         "operation": "mqtt_remote",
    //         "param":{"serverIp":"129.204.245.148"}
    //     },
    //     "method": "thing.gate.debug"
    // }
    static async debug_mqtt_remote(param) {
        if(param) {
            try{
                await CommunicationManager.default.destroyRemoteMqttClient();
                await CommunicationManager.default.createRemoteMqttClient(param.serverIp, (status)=>{
                    DebugManager.commonAnswer2Remote("远程连接情况：" + status);
                });
            }catch(error) {
                DebugManager.commonAnswer2Remote("remote mqtt exception：" + error);
            }
        }
    }

    // {
    //     "params": {
    //         "operation": "eval",
    //         "param":{"eval":"DataCenter.default.gateId"}
    //     },
    //     "method": "thing.gate.debug"
    // }
    // {
    //     "params": {
    //         "operation": "eval",
    //         "param":{"eval":" (async () => {let ret = await XLog.default.getLogPath(); resolve(ret)})()", "async":1}
    //     },
    //     "method": "thing.gate.debug"
    // }
    static async debug_eval(param) {
        try{
            if(param.async) {
                const waitEval = (ev) => {
                    return new Promise((resolve, reject) => {
                      eval(ev);
                    });
                };
                const ret = await waitEval(param.eval);
                DebugManager.commonAnswer2Remote(`${ret}`);
            } else {
                DebugManager.commonAnswer2Remote(eval(param.eval));
            }
        }catch(error) {
            console.log(error);
            DebugManager.commonAnswer2Remote("eval exception：" + error);
        }
    }

    // {
    //     "params": {
    //         "operation": "topic",
    //         "param": {
    //             "topic": "tunnel",
    //             "remote":false,
    //            "ack":1,
    //             "params":""
    //         }
    //     },
    //     "method": "thing.gate.debug"
    // }
    static debug_topic(param) {
        try{
            let topicObj = LogicConstant.Topic_Map[param.topic];
            if(topicObj) {
                let reqParams = param.params ? JSON.parse(param.params) : null;
                if(!param.remote) {
                    CommunicationManager.default.send2Master(TopicUtil.formatterSendTopic(topicObj),
                    Utils.commonMakeMqttRequest(param.ack, reqParams, topicObj.method));
                } else {
                    CommunicationManager.default.send2Remote(TopicUtil.formatterSendTopic(topicObj),
                    Utils.commonMakeMqttRequest(param.ack, reqParams, topicObj.method));
                }
            } else {
                DebugManager.commonAnswer2Remote("no topic :" + param.topic);
            }
        }catch(error) {
            console.log(error);
            DebugManager.commonAnswer2Remote("topic exception：" + error);
        }
    }

    // {
    //     "params": {
    //         "operation": "log",
    //         "param": {
    //             "level": 2
    //         }
    //     },
    //     "method": "thing.gate.debug"
    // }

    // public static final int LEVEL_VERBOSE = 0;
    // public static final int LEVEL_DEBUG = 1;
    // public static final int LEVEL_INFO = 2;
    // public static final int LEVEL_WARNING = 3;
    // public static final int LEVEL_ERROR = 4;
    // public static final int LEVEL_FATAL = 5;
    // public static final int LEVEL_NONE = 6;
    static async debug_log(param) {
        try{
            let level = await XLog.default.getLogLevel();
            let log_path = await XLog.default.getLogPath(); 
            let cache_path = await XLog.default.getCachePath();
            DebugManager.commonAnswer2Remote("Log level:" + level + "|PATH:" + log_path + "|CACHE:" + cache_path);
            //await XLog.default.setLogLevel(param.level/1);
        }catch(error) {
            console.log(error);
            DebugManager.commonAnswer2Remote("log exception：" + error?.message);
        }
    }

    // {
    //     "params": {
    //         "operation": "upgrade",
    //         "param": {
    //             "url": "https://jianli-static-1255466169.cos.ap-guangzhou.myqcloud.com/supervise_v0.1.7_release.apk"
    //         }
    //     },
    //     "method": "thing.gate.debug"
    // }
    static async debug_upgrade(param) {
        try{
            await UpgradeLibrary.doNewVersionUpdate(param.url, param.progress||1);
        }catch(error) {
            console.log(error);
            DebugManager.commonAnswer2Remote("upgrade exception：" + error?.message);
        }
    }

    // {
    //     "params": {
    //         "operation": "command",
    //         "param": {
    //             "cmd": "am start -n com.tenroad.supervise/com.tenroad.supervise.MainActivity"
    //         }
    //     },
    //     "method": "thing.gate.debug"
    // }
    static async debug_command(param) {
        try{
            let result = await UpgradeLibrary.execCommand(param.cmd);
            DebugManager.commonAnswer2Remote("command ret：" + result);
        }catch(error) {
            console.log(error);
            DebugManager.commonAnswer2Remote("command exception：" + error?.message);
        }
    }

    // {
    //     "params": {
    //         "operation": "serial",
    //         "param": {
    //             "type": 1 for loop / 2 for meter / 3 for openDevice test
    //             "event": "readLight"/"readMeter"/"readAddress"
    //             "message": eg -- {"event": "setLampLight", "data": [{"lamp": lamp, "valid": 1, "light": value}]}
    //             "device": "index",
    //             "product": "LoopController" or "SmartMeter"
    //         }
    //     },
    //     "method": "thing.gate.debug"
    // }
    static async debug_serial(param){
        try{
            console.log("debug_serial: ", param);
            if(param.type == 1){        // loop
                if(param.event == "readLight"){
                    if(param.device == null || param.device.length == ""){
                        for(var device of DataCenter.default.loopControllerList){
                            SerialPortManager.default.sendLoopControllerRequest({"event": "readLight"}, device.index);
                        }
                    }else{
                        SerialPortManager.default.sendLoopControllerRequest({"event": "readLight"}, param.device);
                    }                    
                } else if(param.event == "readAddress"){
                    if(param.device == null || param.device.length == ""){
                        for(var device of DataCenter.default.loopControllerList){
                            SerialPortManager.default.sendLoopControllerRequest({"event": "readAddress"}, device.index);
                        }
                    }else{
                        SerialPortManager.default.sendLoopControllerRequest({"event": "readAddress"}, param.device);
                    }
                } else if (param.message){
                    if(param.device == null || param.device.length == ""){
                        for(var device of DataCenter.default.loopControllerList){
                            SerialPortManager.default.sendLoopControllerRequest(JSON.parse(param.message), device.index);
                        }
                    }else{
                        SerialPortManager.default.sendLoopControllerRequest(JSON.parse(param.message), param.device);
                    }
                }
                DebugManager.commonAnswer2Remote("command debug_serial finished");
            } else if(param.type == 2){
                if(param.event == "readMeter"){
                    if(param.device == null || param.device.length == ""){
                        for(var device of DataCenter.default.smartMeterList){
                            SerialPortManager.default.sendMeterRequest(device.index);
                        }
                    }else{
                        SerialPortManager.default.sendMeterRequest(param.device);
                    }                    
                }
                DebugManager.commonAnswer2Remote("command debug_serial finished");
            } else if(param.type == 3){
                if(param.message){
                    await SerialPortManager.default.createDevice(param.product, JSON.parse(param.message), (success) => {
                        DebugManager.commonAnswer2Remote("open device " + JSON.stringify(success) + " success");
                    }, (fail) =>{
                        DebugManager.commonAnswer2Remote("open device " + JSON.stringify(fail) + " failed");
                    });
                }
            }
            
        }catch(error) {
            console.log(error);
            DebugManager.commonAnswer2Remote("debug_serial exception：" + error?.message);
        }
    }
}